﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using OpenNETCF.Security.Cryptography;
using System.Security.Cryptography;
using System.Web;
using System.Net;
using System.IO;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Collections.Specialized;

namespace FFWinMobile
{
    /// <summary>
    /// FFHelper class is contains helper methods for OAuth system
    /// </summary>
    public class FFHelper
    {
        /// <summary>
        /// GenerateTimeStamp method generates TimeStamp value.
        /// </summary>
        /// <returns></returns>
        public string GenerateTimeStamp()
        {

            TimeSpan ts = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0));
            string timeStamp = Convert.ToInt64(ts.TotalSeconds).ToString();
            return timeStamp;
        }
        /// <summary>
        /// Nonce is a unique string based value. GetNonce method generates this value
        /// </summary>
        /// <param name="length"></param>
        /// <returns></returns>
        public string GetNonce(int length)
        {
            string allowedCharacters = "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789";
            StringBuilder password = new StringBuilder();
            Random rand = new Random();

            for (int i = 0; i < length; i++)
            {
                password.Append(allowedCharacters[rand.Next(0, (allowedCharacters.Length - 1))]);
            }
            return password.ToString();

        }
    }
    /// <summary>
    /// FF class is the core class for FFWinMobile. All communication with FriendFeed made in this class 
    /// </summary>
   public static class FF
    {
       public enum ReadFeedWith
       {
           NoCommentsNoLikes,
           WithCommentsAndLikes
       }
       /// <summary>
       /// consumerKey is required from OAuth system and supplied from FriendFeed
       /// </summary>
       private static string consumerKey;

       /// <summary>
       /// consumerSecret is required from OAuth system and supplied from FriendFeed
       /// </summary>
       private static string consumerSecret;
       
       /// <summary>
       /// Static constructor assigns initial values for consumerKey and consumerSecter
       /// </summary>     
       static FF()
       {
           consumerKey = "49b1f74e66a840f996048af82389e1d5";
           consumerSecret = "8e9b65758ab149878ed868776cd82060f3e5a1d0b0994657bb5051ba18c0212c";
           System.Net.ServicePointManager.CertificatePolicy = new TrustAllCertificatePolicy();
       }
     /// <summary>
     /// Login method authenticate user to FriendFeed system
     /// </summary>
     /// <param name="userName">User's FriendFeed's username</param>
     /// <param name="passWord">User's FriendFeed's password</param>
     /// <param name="message">Response</param>
     /// <returns></returns>
        public static bool Login(string userName, string passWord, out string message)
        {
            Uri uri = new Uri("https://friendfeed.com/account/oauth/ia_access_token");           

            FFHelper helper = new FFHelper();
              ASCIIEncoding encoding=new ASCIIEncoding();

                HMACSHA1 sha1 = new HMACSHA1();
                byte[] key = Encoding.ASCII.GetBytes(consumerSecret+"&"+"");
                if (key.Length > 64)
                {
                   
                    SHA1CryptoServiceProvider coreSha1 = new SHA1CryptoServiceProvider();
                    key = coreSha1.ComputeHash(key);
                }
                sha1.Key = key;

            string timeStamp = helper.GenerateTimeStamp();
            System.Collections.Generic.List<string> parameters = new System.Collections.Generic.List<string>();
          
            parameters.Add("oauth_consumer_key=" + HttpUtility.UrlEncode(consumerKey));
            parameters.Add("oauth_nonce=" + HttpUtility.UrlEncode(helper.GetNonce(7)));
            parameters.Add("oauth_timestamp=" + timeStamp);
            parameters.Add("oauth_signature_method=HMAC-SHA1");
            parameters.Add("oauth_version=1.0");
            parameters.Add("ff_username=" + userName);
            parameters.Add("ff_password=" + passWord);

            parameters.Sort();
            string parametersStr = string.Join("&", parameters.ToArray());

           
               string baseStr = "GET"+"&" +
                    HttpUtility.UrlEncode(uri.ToString()) + "&" +
                   HttpUtility.UrlEncode(parametersStr);
          
            
                byte[] baseStringBytes = Encoding.UTF8.GetBytes(baseStr.Replace("%3d","%3D").Replace("%3a","%3A").Replace("%2f","%2F"));
                byte[] baseStringHash = sha1.ComputeHash(baseStringBytes);
                String base64StringHash = Convert.ToBase64String(baseStringHash);
                String encBase64StringHash = HttpUtility.UrlEncode(base64StringHash);
                 
                parameters.Add("oauth_signature=" + encBase64StringHash);
                parameters.Sort();
               
                string requestUrl = uri.ToString() + "?" + string.Join("&", parameters.ToArray());
                HttpWebRequest r = (HttpWebRequest)HttpWebRequest.Create(requestUrl);
                
            r.Method = "GET";

            r.ContentType = "application/x-www-form-urlencoded";
            
            try
            {

                HttpWebResponse response = (HttpWebResponse)r.GetResponse();
                UserName = userName;
                Password = passWord;

               string cevap = new StreamReader(response.GetResponseStream()).ReadToEnd();
               string[] gelenler = cevap.Split('&');
               oauth_token = gelenler[1].Split('=')[1];
               oauth_token_secret = gelenler[0].Split('=')[1];
               
                response.Close();
                GF.OAuthToken = oauth_token;
                GF.OAuthTokenSecret = oauth_token_secret;                
                message = cevap;
                return true;
            }
            catch (WebException ex)
            {
                message = ex.Message;
                return false;
            }
            }
       
        public static string ReadHomeFeed(int curPos)
        {
            return ReadHomeFeed(ReadFeedWith.NoCommentsNoLikes, curPos);
        }
        public static string ReadHomeFeed(ReadFeedWith w, int curPos)
        {
            string msg;
            List<string> parameters = new List<string>();
            parameters.Add("start=" + curPos);
            parameters.Add("num="+ GF.PageRecordCount);
            if (w == ReadFeedWith.NoCommentsNoLikes)
            {
                parameters.Add("maxcomments=0");
                parameters.Add("maxlikes=0");
            }
            else
            {
                parameters.Add("maxcomments=auto");
                parameters.Add("maxlikes=auto");
            }
            parameters.Add("fof=1");
            parameters.Add("raw=1");
            if (UserRequest("http://friendfeed-api.com/v2/feed/home", UserName, Password, oauth_token, oauth_token_secret,parameters, out msg))
            {
                return msg;
            }
            else
                return "error";
        }
        public static string ReadFeed(string id)
        {
            string msg;
            List<string> parameters = new List<string>();
           
            parameters.Add("raw=1");
            if (UserRequest("http://friendfeed-api.com/v2/feed/"+id, UserName, Password, oauth_token, oauth_token_secret, parameters, out msg))
            {
                return msg;
            }
            else
                return "error";
        }
        public static int ReadHomeFeedCount()
        {
            string msg;
            List<string> parameters = new List<string>();
            
                parameters.Add("maxcomments=0");
                parameters.Add("maxlikes=0");
                parameters.Add("fof=1");
           
            if (UserRequest("http://friendfeed-api.com/v2/feed/home", UserName, Password, oauth_token, oauth_token_secret, parameters, out msg))
            {
                JObject j = JObject.Parse(msg);
                JArray entries = (JArray)j["entries"];
                return entries.Count;
            }
            else
                return 0;
        }
        public static string ReadUserFeed(string username, int curPos)
        {
            return ReadUserFeed(ReadFeedWith.NoCommentsNoLikes, username, curPos);
        }
        public static string ReadUserFeed(ReadFeedWith w, string username, int curPos)
        {
            string msg;
            List<string> parameters = new List<string>();
            parameters.Add("start=" + curPos);
            parameters.Add("num="+ GF.PageRecordCount);
            if (w == ReadFeedWith.NoCommentsNoLikes)
            {
                parameters.Add("maxcomments=0");
                parameters.Add("maxlikes=0");
            }
            else
            {
                parameters.Add("maxcomments=auto");
                parameters.Add("maxlikes=auto");
            }
            parameters.Add("fof=1");
            parameters.Add("raw=1");
            if (UserRequest("http://friendfeed-api.com/v2/feed/" + username, UserName, Password, oauth_token, oauth_token_secret, parameters, out msg))
            {
                return msg;
            }
            else
            {
                if (msg.Contains("Forbidden"))
                {
                    return "forbidden";
                }
                else{
                    return "error";
                }
            }
        }
        public static int ReadUserFeedCount(string username)
        {
            string msg;
            List<string> parameters = new List<string>();

            parameters.Add("maxcomments=0");
            parameters.Add("maxlikes=0");

            if (UserRequest("http://friendfeed-api.com/v2/feed/home" + username, UserName, Password, oauth_token, oauth_token_secret, parameters, out msg))
            {
                JObject j = JObject.Parse(msg);
                JArray entries = (JArray)j["entries"];
                return entries.Count;
            }
            else
                return 0;
        }
        public static string ReadSearchedFeeds(string key, int curPos)
        {
            return ReadSearchedFeeds(ReadFeedWith.NoCommentsNoLikes, key, curPos);
        }
        public static string ReadSearchedFeeds(string key, int curPos, string where, string what)
        {
            return ReadSearchedFeeds(ReadFeedWith.NoCommentsNoLikes, key, curPos, where, what);
        }
        public static string ReadSearchedFeeds(ReadFeedWith w, string key, int curPos)
        {
            return ReadSearchedFeeds(w, key, curPos, null, null);
        }
        public static string ReadSearchedFeeds(ReadFeedWith w, string key, int curPos, string where, string what)
        {
            string msg;
            List<string> parameters = new List<string>();
            parameters.Add("start=" + curPos);
            parameters.Add("num=" + GF.PageRecordCount);
            if (w == ReadFeedWith.NoCommentsNoLikes)
            {
                parameters.Add("maxcomments=0");
                parameters.Add("maxlikes=0");
            }
            else
            {
                parameters.Add("maxcomments=auto");
                parameters.Add("maxlikes=auto");
            }
            parameters.Add("raw=1");
            key = System.Uri.EscapeDataString(key);

            parameters.Add("q=" + key);
            if (!string.IsNullOrEmpty(where) && !string.IsNullOrEmpty(what))
                parameters.Add(where + "=" + what);
            if (UserRequest("http://friendfeed-api.com/v2/search", UserName, Password, oauth_token, oauth_token_secret, parameters, out msg))
            {
                return msg;
            }
            else
                return "error";
        }
        public static int ReadSearchedFeeds(string key)
        {
            string msg;
            List<string> parameters = new List<string>();

            parameters.Add("maxcomments=0");
            parameters.Add("maxlikes=0");
            key = System.Uri.EscapeDataString(key);

            parameters.Add("q=" + key);
            if (UserRequest("http://friendfeed-api.com/v2/feed/search" , UserName, Password, oauth_token, oauth_token_secret, parameters, out msg))
            {
                JObject j = JObject.Parse(msg);
                JArray entries = (JArray)j["entries"];
                return entries.Count;
            }
            else
                return 0;
        }
        public static string FeedCreate(string body,string to)
        {
            string msg;
            List<string> parameters = new List<string>();
            string url = "http://friendfeed-api.com/v2/entry";
            body = System.Uri.EscapeDataString(body);
            parameters.Add("body=" + body);
            if (!string.IsNullOrEmpty(to))
            {
                to = System.Uri.EscapeDataString(to);
                parameters.Add("to=" + to);
            }
            if (UserRequest(url, UserName, Password, oauth_token, oauth_token_secret, parameters, "POST", out msg))
            {
                return msg;
            }
            else
                return "error";
        }
        public static string PostComment(string body, string id)
        {
            string msg;
            List<string> parameters = new List<string>();
            string url = "http://friendfeed-api.com/v2/comment";
            body = System.Uri.EscapeDataString(body);
            parameters.Add("body=" + body);
            id = System.Uri.EscapeDataString(id);
            parameters.Add("entry=" + id);
            if (UserRequest(url, UserName, Password, oauth_token, oauth_token_secret, parameters, "POST", out msg))
            {
                return msg;
            }
            else
                return "error";
        }
        public static string LikeEntry(string id)
        {
            string msg;
            List<string> parameters = new List<string>();
            string url = "http://friendfeed-api.com/v2/like";
           
            id = System.Uri.EscapeDataString(id);
            parameters.Add("entry=" + id);
            if (UserRequest(url, UserName, Password, oauth_token, oauth_token_secret, parameters, "POST", out msg))
            {
                return msg;
            }
            else
                return "error";
        }
        public static string DeleteLike(string id)
        {
            string msg;
            List<string> parameters = new List<string>();
            string url = "http://friendfeed-api.com/v2/like/delete";

            id = System.Uri.EscapeDataString(id);
            parameters.Add("entry=" + id);
            if (UserRequest(url, UserName, Password, oauth_token, oauth_token_secret, parameters, "POST", out msg))
            {
                return msg;
            }
            else
                return "error";
        }
        public static string FeedSubscribe(string feed_id, string list_id)
        {
            string msg;
            List<string> parameters = new List<string>();
            string url = "http://friendfeed-api.com/v2/subscribe";
            if (!string.IsNullOrEmpty(feed_id))
            {
                feed_id = System.Uri.EscapeDataString(feed_id);
               
                parameters.Add("feed=" + feed_id);
            }
            if (!string.IsNullOrEmpty(list_id))
            {
                list_id = System.Uri.EscapeDataString(list_id);
                parameters.Add("list=" + list_id);
            }
            
            if (UserRequest(url, UserName, Password, oauth_token, oauth_token_secret, parameters,"POST", out msg))
            {
                return msg;
            }
            else
                return "error";
        }
        public static string FeedUserLists()
        {
            string msg;
           
            if (UserRequest("http://friendfeed-api.com/v2/feedlist", UserName, Password, oauth_token, oauth_token_secret, null, out msg))
            {
                return msg;
            }
            else
                return "error";
        }
        public static string FeedInfo(string feed_id)
        {
            string msg;

            if (UserRequest("http://friendfeed-api.com/v2/feedinfo/"+ feed_id, UserName, Password, oauth_token, oauth_token_secret, null, out msg))
            {
                return msg;
            }
            else
                return "error";
        }
        public static bool Validate()
        {
            string msg;
            bool response = UserRequest("http://friendfeed-api.com/v2/validate", null, null, GF.OAuthToken,GF.OAuthTokenSecret, null, out msg);
            if (response)
            {
                oauth_token = GF.OAuthToken;
                oauth_token_secret = GF.OAuthTokenSecret;
            }
            return response;
            
        }
        public static string FeedUnSubscribe(string feed_id)
        {
            string msg;
            List<string> parameters = new List<string>();
            string url = "http://friendfeed-api.com/v2/unsubscribe";
            if (!string.IsNullOrEmpty(feed_id))
            {
                feed_id = System.Uri.EscapeDataString(feed_id);

                parameters.Add("feed=" + feed_id);
            }
            if (UserRequest(url, UserName, Password, oauth_token, oauth_token_secret, parameters,"POST", out msg))
            {
                return msg;
            }
            else
                return "error";
        }
        public static bool UserRequest(string url, string userName, string passWord, string oauth_token, string oauth_token_secret, List<string> param, out string message)
        {
            return UserRequest(url, userName, passWord, oauth_token, oauth_token_secret, param, "GET", out message);
        }
        public static bool UserRequest(string url, string userName, string passWord, string oauth_token, string oauth_token_secret,List<string> param,string httpMethod, out string message)
        {
            Uri uri = new Uri(url);
            string consumerKey, consumerSecret;
            consumerKey = "49b1f74e66a840f996048af82389e1d5";
            consumerSecret = "8e9b65758ab149878ed868776cd82060f3e5a1d0b0994657bb5051ba18c0212c";
            FFHelper helper = new FFHelper();

            ASCIIEncoding encoding = new ASCIIEncoding();

            HMACSHA1 sha1 = new HMACSHA1();
            byte[] key = Encoding.ASCII.GetBytes(consumerSecret + "&" + oauth_token_secret);
            if (key.Length > 64)
            {

                SHA1CryptoServiceProvider coreSha1 = new SHA1CryptoServiceProvider();
                key = coreSha1.ComputeHash(key);
            }
            sha1.Key = key;

            string timeStamp = helper.GenerateTimeStamp();
            System.Collections.Generic.List<string> parameters = new System.Collections.Generic.List<string>();
         
            parameters.Add("oauth_consumer_key=" + HttpUtility.UrlEncode(consumerKey));
            parameters.Add("oauth_nonce=" + HttpUtility.UrlEncode(helper.GetNonce(7)));
            parameters.Add("oauth_timestamp=" + timeStamp);
            parameters.Add("oauth_signature_method=HMAC-SHA1");
            parameters.Add("oauth_version=1.0");
            parameters.Add("oauth_token=" + HttpUtility.UrlEncode(oauth_token));
            if (param != null)
                parameters.AddRange(param);
            
            parameters.Sort();
            string parametersStr = string.Join("&", parameters.ToArray());

        
            string baseStr = httpMethod+ "&" +
                 HttpUtility.UrlEncode(uri.ToString()) + "&" +
                HttpUtility.UrlEncode(parametersStr);

            /* generate the signature and add it to our parameters */
            string lastString = baseStr.Replace("%3d", "%3D").Replace("%3a", "%3A").Replace("%2f", "%2F").Replace("(", "%2528").Replace(")","%2529");
            byte[] baseStringBytes = Encoding.ASCII.GetBytes(lastString);
            byte[] baseStringHash = sha1.ComputeHash(baseStringBytes);
            String base64StringHash = Convert.ToBase64String(baseStringHash);
            String encBase64StringHash = HttpUtility.UrlEncode(base64StringHash);

            parameters.Add("oauth_signature=" + encBase64StringHash);
            parameters.Sort();
            HttpWebRequest r = null;
            string requestUrl = uri.ToString() + "?" + string.Join("&", parameters.ToArray());
            if (httpMethod == "GET")
            {
                
                r = (HttpWebRequest)HttpWebRequest.Create(requestUrl);
                r.Method = httpMethod;
                r.ContentType = "application/x-www-form-urlencoded";
               
            }
            else if (httpMethod == "POST")
            {
                parametersStr = string.Join("&", parameters.ToArray());
              
            string    normalizedUrl = string.Format("{0}://{1}", uri.Scheme, uri.Host);
                if (!((uri.Scheme == "http" && uri.Port == 80) || (uri.Scheme == "https" && uri.Port == 443)))
                {
                    normalizedUrl += ":" + uri.Port;
                }
                normalizedUrl += uri.AbsolutePath;

                r = (HttpWebRequest)HttpWebRequest.Create(normalizedUrl);
                
                r.ContentType = "application/x-www-form-urlencoded";

                byte[] bytes = Encoding.ASCII.GetBytes(parametersStr);
                r.ContentLength = bytes.Length;

                r.Method = httpMethod.ToUpper();
                Stream s = r.GetRequestStream();
               
                s.Write(bytes,0,bytes.Length);
                
                s.Close();
               
            }
            

            try
            {

                WebResponse res = r.GetResponse();
                HttpWebResponse response = (HttpWebResponse)res;
                string cevap = new StreamReader(response.GetResponseStream()).ReadToEnd();

                response.Close();
                message = cevap;
                return true;
            }
            catch (WebException ex)
            {
                if (ex.Message == "This protocol version is not supported.")
                {
                    message = string.Empty;
                    return true;
                }
               
                message = ex.Message;
                return false;
            }



        }
        public static string UserName { get; set; }
        public static string Password { get; set; }
        public static string oauth_token { get; set; }
        public static string oauth_token_secret { get; set; }

      
         
        }
   
    }

